import time

import pyglet
from pyglet.gl import *

import cocos
from cocos.director import director

PADDING = 8
COLOR_ENABLED = (80, 80, 80, 255)
COLOR_DISABLED = (180, 180, 180, 255)
COLOR_HOVERED = (0, 0, 0, 255)

class PopupMenu(cocos.layer.Layer):
    is_event_handler = True

    def __init__(self, x, y, options, on_close):
        super(PopupMenu, self).__init__()

        self.batch = pyglet.graphics.Batch()
        self.on_close = on_close

        ox, oy = x, y

        self.options = []
        y = y
        self.menu_width = 0
        for value, label, enabled in options:
            if enabled:
                color = COLOR_ENABLED
            else:
                color = COLOR_DISABLED
            l = pyglet.text.Label(label, x=x, y=y, color=color,
                anchor_y='top', batch=self.batch)
            l._value = value
            l._enabled = enabled
            self.options.append(l)
            self.menu_width = max(self.menu_width, l.content_width)
            y -= l.content_height

        self.menu_height = abs(oy - y)

        # add some padding
        self.menu_height += PADDING*2
        self.menu_width += PADDING*2

        # adjust menu position to make sure whole menu is visible
        parent_w, parent_h = director.get_window_size()
        if ox < 0:
            ox = 0
        if ox + self.menu_width> parent_w:
            ox = parent_w - self.menu_width
        if oy - self.menu_height < 0:
            oy = self.menu_height
        if oy > parent_h:
            oy = parent_h

        # reposition the items
        y = oy - PADDING
        for option in self.options:
            option.x = ox + PADDING
            option.y = y
            y -= l.content_height

        self.created_time = time.time()

        # backdrop for the menu
        self.menu_x = x1 = ox
        self.menu_y = y1 = oy
        x2 = ox + self.menu_width
        y2 = oy - self.menu_height
        self.quad = self.batch.add(4, pyglet.gl.GL_QUADS, None,
            ('v3i', (x1, y1, -1, x2, y1, -1, x2, y2, -1, x1, y2, -1)),
            ('c4B', (255, 255, 255, 220) * 4),
        )

    def on_mouse_motion(self, x, y, dx, dy):
        '''
        Absorb all events
        # basic bounds check
        if x < self.menu_x or x > self.menu_x + self.menu_width:
            return pyglet.event.EVENT_UNHANDLED
        if y > self.menu_y or y < self.menu_y - self.menu_height:
            return pyglet.event.EVENT_UNHANDLED
        '''

        for option in self.options:
            if not option._enabled: continue
            if (option.x < x < option.x + self.menu_width and
                    option.y - option.content_height < y < option.y):
                option.color = COLOR_HOVERED
            elif option.color == (0, 0, 0, 255):
                option.color = COLOR_ENABLED
        return pyglet.event.EVENT_HANDLED

    def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
        return self.on_mouse_motion(x, y, dx, dy)

    # absorb all key press events
    def on_key_press(self, symbol, modifiers):
        if symbol == pyglet.window.key.ESCAPE:
            self.close_menu()
        return True
    def on_text(self, *args): return True
    on_text_motion = on_text
    on_text_motion = on_text

    def on_mouse_press(self, x, y, buttons, modifiers):
        # determine action to take
        selected_option = None
        for option in self.options:
            if not option._enabled: continue
            if (option.x < x < option.x + self.menu_width and
                    option.y - option.content_height < y < option.y):
                selected_option = option._value
                break
        self.close_menu(selected_option)

    def close_menu(self, selected_option=None):
        self.parent.remove(self)
        self.options = None
        self.quad = None
        self.batch = None
        self.on_close(selected_option)
        return pyglet.event.EVENT_HANDLED

    def on_mouse_release(self, x, y, button, modifiers):
        if time.time() - self.created_time > .5:
            # after a half a second assume user has dragged to item so
            # fake a press to generate the item selection event
            return self.on_mouse_press(x, y, button, modifiers)
        return pyglet.event.EVENT_UNHANDLED

    def draw(self):
        self.transform()
        self.batch.draw()

